package cn.jszhao.common.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 持久化数据脱敏工具类 <br>
 * 使用国密SM4对称加密算法
 *
 * @author 紫麒麟vip
 *
 */
public class DataMaskingUtil {

    private static final Logger log = LoggerFactory.getLogger(DataMaskingUtil.class);

    // key必须是16字节，即128位
    private static final String key = "Wonders300168,.!";
    // 指明加密算法和密钥
    private static final SymmetricCrypto sm4 = new SymmetricCrypto("SM4/ECB/PKCS5Padding", key.getBytes());
    // 加密标识
    private static final String SMENCRYPT_PRE = "DM@";

    /**
     * 将明文字符串加密成密文后，加上SMENCRYPT_PRE作为前缀
     *
     * @param plainStr
     *            明文字符串！!
     * @return 密文,并且加上 SMENCRYPT_PRE 前缀
     */
    public static String encrypt(String plainStr) {
        log.debug(Thread.currentThread().getId() + "=>plainStr=" + plainStr);
        if (StrUtil.isEmpty(plainStr) || isEncryptBySMCrypto(plainStr) == true) {
            log.debug(Thread.currentThread().getId() + "=>encResult=" + plainStr);
            return plainStr;
        }
        String encResult = sm4.encryptHex(plainStr);
        log.debug(Thread.currentThread().getId() + "=>encResult=" + encResult);
        return SMENCRYPT_PRE + encResult;
    }

    /**
     * 国密算法解密，要有前缀SMENCRYPT_PRE
     *
     * @param encStr
     *            加密字符串，要有前缀SMENCRYPT_PRE，表示是通过国密算法加密的
     * @return
     */
    public static String decrypt(String encStr) {
        log.debug(Thread.currentThread().getId() + "=>encStr=" + encStr);
        if (StrUtil.isEmpty(encStr) || isEncryptBySMCrypto(encStr) == false) {
            log.debug(Thread.currentThread().getId() + "=>decResult=" + encStr);
            return encStr;
        }
        String decResult = null;
        String removePre = StrUtil.removePrefix(encStr, SMENCRYPT_PRE);
        decResult = sm4.decryptStr(removePre);
        log.debug(Thread.currentThread().getId() + "=>decResult=" + decResult);
        return decResult;
    }

    /**
     * 判断是否用国密算法加密过，通过判断前缀是否有SMENCRYPT_PRE
     *
     * @return 有SMENCRYPT_PRE为true表示用了国密算法加密了
     */
    public static boolean isEncryptBySMCrypto(String encStr) {
        return StrUtil.startWith(encStr, SMENCRYPT_PRE);
    }

}
